home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 42
/
Amiga Format AFCD42 (Issue 126, Aug 1999).iso
/
-serious-
/
comms
/
other
/
slrn
/
slrn_src
/
src
/
slrn.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-05-14
|
35KB
|
1,710 lines
/* -*- mode: C; mode: fold -*- */
/* Copyright (c) 1998 John E. Davis (davis@space.mit.edu)
*
* This file is part of slrn.
*
* Slrn is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* Slrn is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* along with Slrn; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "slrnfeat.h"
/*{{{ Include files */
#include <stdio.h>
#include <signal.h>
#include <string.h>
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef VMS
# include "vms.h"
#else
# if !defined(sun) && !defined(IBMPC_SYSTEM)
# include <sys/ioctl.h>
# endif
# ifdef HAVE_TERMIOS_H
# include <termios.h>
# endif
# ifdef SYSV
# include <sys/termio.h>
# include <sys/stream.h>
# include <sys/ptem.h>
# include <sys/tty.h>
# endif
# ifndef __os2__
# include <sys/types.h>
# include <sys/stat.h>
# endif
#endif /* !VMS */
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
#include <slang.h>
#include "jdmacros.h"
#include <errno.h>
#include "server.h"
#include "slrn.h"
#include "group.h"
#include "misc.h"
#include "startup.h"
#include "art.h"
#include "score.h"
#include "util.h"
#include "chmap.h"
#if SLRN_USE_SLTCP
# include "sltcp.h"
#endif
#if SLRN_HAS_GROUPLENS
# include "grplens.h"
#endif
#if SLRN_HAS_SLANG
# include "interp.h"
#endif
#ifdef __os2__
# define INCL_VIO
# include <os2.h>
#endif
#if defined(__NT__) || defined(__WIN32__)
# include <windows.h>
#endif
/*}}}*/
/*{{{ Global Variables */
int Slrn_TT_Initialized = 0;
/* If -1, force mouse. If 1 the mouse will be used on in XTerm. If 0,
* do not use it.
*/
int Slrn_Use_Mouse;
int Slrn_Batch;
int Slrn_Suspension_Ok;
char *Slrn_Newsrc_File = NULL;
char *Slrn_Lib_Dir = NULL;
Slrn_Mode_Type *Slrn_Current_Mode;
int Slrn_Default_Server_Obj = SLRN_DEFAULT_SERVER_OBJ;
int Slrn_Default_Post_Obj = SLRN_DEFAULT_POST_OBJ;
/*}}}*/
/*{{{ Static Variables */
static int Can_Suspend;
static volatile int Want_Suspension;
static volatile int Want_Window_Size_Change;
static void perform_suspend (int);
static int Current_Mouse_Mode;
/*}}}*/
/*{{{ Static Function Declarations */
static int suspend_display_mode (int);
static int resume_display_mode (int, int, int);
static void init_suspend_signals (int);
static void slrn_hangup (int);
static void run_winch_functions (int, int);
/*}}}*/
/*{{{ Newsrc Locking Routines */
static void test_lock( char *file ) /*{{{*/
{
int pid;
FILE *fp;
if ((fp = fopen (file, "r")) != NULL)
{
if (1 == fscanf (fp, "%d", &pid) )
{
if ((pid > 0)
#if !defined(IBMPC_SYSTEM)
&& (0 == kill (pid, 0))
#endif
)
{
#if defined(IBMPC_SYSTEM)
slrn_exit_error ("\
slrn: pid %d is locking the newsrc file. If you're not running another\n\
copy of slrn, delete the file %s",
pid, file);
#else
slrn_exit_error ("slrn: pid %d is locking the newsrc file.", pid);
#endif
}
}
slrn_fclose (fp);
}
}
/*}}}*/
static int make_lock( char *file ) /*{{{*/
{
int pid;
FILE *fp;
#ifdef VMS
fp = fopen (file, "w", "fop=cif");
#else
fp = fopen (file, "w");
#endif
if (fp == NULL) return -1;
pid = getpid ();
if (EOF == fprintf (fp, "%d", pid))
{
slrn_fclose (fp);
return -1;
}
return slrn_fclose (fp);
}
/*}}}*/
static void lock_file (int how) /*{{{*/
{
char file[SLRN_MAX_PATH_LEN];
char name[256];
static int not_ok_to_unlock;
#if SLRN_HAS_RNLOCK
int rnlock = 0;
char file_rn[SLRN_MAX_PATH_LEN];
#endif
if (Slrn_Newsrc_File == NULL) return;
if (not_ok_to_unlock) return;
not_ok_to_unlock = 1;
#ifdef SLRN_USE_OS2_FAT
slrn_os2_make_fat (name, Slrn_Newsrc_File, ".lck");
#else
sprintf (name, "%s-lock", Slrn_Newsrc_File);
#endif
slrn_make_home_filename (name, file);
#if SLRN_HAS_RNLOCK
if (0 == strcmp(".newsrc", Slrn_Newsrc_File))
{
rnlock = 1;
slrn_make_home_filename (".rnlock", file_rn);
}
#endif
if (how == 1)
{
test_lock (file);
#if SLRN_HAS_RNLOCK
if (rnlock) test_lock (file_rn);
#endif
if (-1 == make_lock (file))
{
slrn_exit_error ("Unable to create lock file %s.", file);
}
#if SLRN_HAS_RNLOCK
if (rnlock && (-1 == make_lock (file_rn)))
{
slrn_delete_file (file); /* delete the "normal" lock file */
slrn_exit_error ("Unable to create lock file %s.", file_rn);
}
#endif
}
else
{
if (-1 == slrn_delete_file (file))
{
/* slrn_exit_error ("Unable to remove lockfile %s.", file); */
}
#if SLRN_HAS_RNLOCK
if (rnlock && -1 == slrn_delete_file (file_rn))
{
/* slrn_exit_error ("Unable to remove lockfile %s.", file_rn); */
}
#endif
}
not_ok_to_unlock = 0;
}
/*}}}*/
/*}}}*/
/*{{{ Signal Related Functions */
/*{{{ Low-Level signal-related utility functions */
static void init_like_signals (int argc, int *argv, /*{{{*/
void (*f0)(int),
void (*f1)(int),
int state)
{
#ifdef HAVE_SIGACTION
struct sigaction sa;
#endif
int i;
if (state == 0)
{
for (i = 0; i < argc; i++)
SLsignal_intr (argv[i], f0);
return;
}
for (i = 0; i < argc; i++)
{
int sig = argv[i];
SLsignal_intr (sig, f1);
#if defined(SLRN_POSIX_SIGNALS)
if (-1 != sigaction (sig, NULL, &sa))
{
int j;
for (j = 0; j < argc; j++)
{
if (j != i) sigaddset (&sa.sa_mask, argv[j]);
}
(void) sigaction (sig, &sa, NULL);
}
#endif
}
}
/*}}}*/
/*}}}*/
/*{{{ Suspension signals */
#ifdef REAL_UNIX_SYSTEM
#define SUSPEND_STACK_SIZE 512
static char Suspend_Stack [SUSPEND_STACK_SIZE];
static unsigned int Suspension_Stack_Depth = 0;
static int Ok_To_Suspend = 0;
#endif
static int Suspend_Sigtstp_Suspension = 0;
void slrn_push_suspension (int ok) /*{{{*/
{
#ifdef REAL_UNIX_SYSTEM
if (Suspension_Stack_Depth < SUSPEND_STACK_SIZE)
{
Suspend_Stack [Suspension_Stack_Depth] = Ok_To_Suspend;
}
else ok = 0;
Suspension_Stack_Depth++;
(void) slrn_handle_interrupts ();
Ok_To_Suspend = ok;
#endif
}
/*}}}*/
void slrn_pop_suspension (void) /*{{{*/
{
#ifdef REAL_UNIX_SYSTEM
if (Suspension_Stack_Depth == 0)
{
slrn_error ("pop_suspension: underflow!");
return;
}
Suspension_Stack_Depth--;
if (Suspension_Stack_Depth < SUSPEND_STACK_SIZE)
{
Ok_To_Suspend = Suspend_Stack [Suspension_Stack_Depth];
}
else Ok_To_Suspend = 0;
(void) slrn_handle_interrupts ();
#endif
}
/*}}}*/
/* This function is called by the SIGTSTP handler. Since it operates
* in an asynchronous fashion, care must be exercised to control when that
* can happen. This is accomplished via the push/pop_suspension functions.
*/
static void sig_suspend (int sig)
{
#ifdef REAL_UNIX_SYSTEM
sig = errno;
if (Ok_To_Suspend
&& (0 == Suspend_Sigtstp_Suspension))
{
perform_suspend (1);
}
else Want_Suspension = 1;
init_suspend_signals (1);
errno = sig;
#endif
}
static void init_suspend_signals (int state) /*{{{*/
{
int argv[2];
int argc = 0;
if (Can_Suspend == 0)
return;
#ifdef SIGTSTP
argv[argc++] = SIGTSTP;
#endif
#ifdef SIGTTIN
argv[argc++] = SIGTTIN;
#endif
init_like_signals (argc, argv, SIG_DFL, sig_suspend, state);
}
/*}}}*/
static void perform_suspend (int smg_suspend_flag) /*{{{*/
{
#if !defined(SIGSTOP) || !defined(REAL_UNIX_SYSTEM)
slrn_error ("Not implemented.");
Want_Suspension = 0;
#else
int init;
int mouse_mode = Current_Mouse_Mode;
# ifdef SLRN_POSIX_SIGNALS
sigset_t mask;
Want_Suspension = 0;
if (Can_Suspend =